mod errors;
mod models;
mod notes_redis_helper;
mod proxy;
mod result;
#[cfg(test)]
mod tests;
mod utils;
use crate::errors::MyError;
use actix_web::middleware::Logger;
use actix_web::{web, App, HttpServer};
use env_logger::Builder;
use log::info;
use log::LevelFilter;
use models::{
    get_app_config, ApiMappingEnv, ApiMappingList, AppConfig, StaticMappingList, UrlMappingEnv,
};
use proxy::handle_proxy;
use redis_pool::{RedisPool, SingleRedisPool};
use reqwest::{redirect::Policy, Client};
use result::MyResult;

fn build_redis_client(redis_addr: &str, redis_port: u16) -> MyResult<redis::Client> {
    let redis_url = format!("redis://{}:{}/0", redis_addr, redis_port);
    let client = redis::Client::open(redis_url).map_err(MyError::RedisError)?;
    Ok(client)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    //init().expect("初始化环境失败");

    let mut builder = Builder::from_default_env();
    builder.filter_level(LevelFilter::Debug);
    builder.init();

    // 初始化client
    let client = Client::builder()
        .redirect(Policy::none())
        .build()
        .expect("build reqwest client错误");

    let config: &AppConfig = get_app_config();
    info!("服务启动 appConfig:{}", config);
    let static_mapping = config
        .static_mapping
        .to_owned()
        .unwrap_or_default()
        .iter()
        .map(|item| UrlMappingEnv::from(item.clone()))
        .collect::<Vec<UrlMappingEnv>>();
    let api_mapping = config
        .api_mapping
        .to_owned()
        .unwrap_or_default()
        .iter()
        .map(|item| ApiMappingEnv::from(item.clone()))
        .collect::<Vec<ApiMappingEnv>>();
    let redis_pool: Option<SingleRedisPool> = config.auth.as_ref().map(|auth| {
        RedisPool::from(
            build_redis_client(&auth.redis_addr, auth.redis_port).expect("创建redis pool 失败"),
        )
    });

    info!("服务启动 url:{}", config.server_addr.clone());
    info!("服务启动 port:{}", config.port);
    HttpServer::new(move || {
        let static_mapping = static_mapping.clone();
        let api_mapping = api_mapping.clone();
        App::new()
            .wrap(Logger::default())
            .wrap(Logger::new("%a %{User_Agent}i"))
            .app_data(web::Data::new(redis_pool.clone()))
            .app_data(web::Data::new(ApiMappingList(api_mapping)))
            .app_data(web::Data::new(StaticMappingList(static_mapping)))
            .app_data(web::Data::new(client.clone()))
            .default_service(web::route().to(handle_proxy)) // 处理所有请求
    })
    .bind((config.server_addr.clone(), config.port))?
    .run()
    .await?;
    Ok(())
}
